package okw.gui;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import okw.database.model.Node;
import okw.manager.ManagerController;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import core.database.NodeType;
import core.exceptions.CommunicationInitiationException;
import core.exceptions.PortInUseException;
import core.utils.ConfigPropertiesHolder;
import core.utils.Converter;
import core.utils.Property;

public class MainWindow implements ApplicationContextAware {
	private static class ContentProvider implements IStructuredContentProvider {
		@SuppressWarnings("unchecked")
		public Object[] getElements(Object inputElement) {
			return ((List<Message>) inputElement).toArray();
		}

		public void dispose() {
		}

		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}
	}

	private static final Logger L = LoggerFactory.getLogger(MainWindow.class);

	public static boolean isDebugMode() {
		return ConfigPropertiesHolder.getInstance().getProperty(Property.DEBUG_STATE).equalsIgnoreCase("true");
	}

	private List<Message> messageList = new ArrayList<Message>();

	private static ManagerController manager;

	protected Shell shlMain;
	private ApplicationContext context;
	private TableViewer tblVwrMain;
	private Table tblMain;
	private Button btnClearMessages;
	private Button btnCheckConnection;

	private DlgCommunicationState dlgCommunicationState;

	public MainWindow() {
		L.debug("Tworzę MainWindow");
		L.debug("Utworzono MainWindow");
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.context = applicationContext;
	}

	public static ManagerController getManager() {
		return manager;
	}

	/**
	 * Open the window.
	 * 
	 * @wbp.parser.entryPoint
	 */
	public void open() {
		final Display display = Display.getDefault();

		manager = context.getBean(ManagerController.class);
		try {
			manager.setUp();
		} catch (CommunicationInitiationException e) {
			e.printStackTrace();
		} catch (PortInUseException e) {
			e.printStackTrace();
		}
		createContents();
		shlMain.open();
		shlMain.layout();

		while (!shlMain.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}

		manager.shutDown();
	}

	public Node askForMainNodeData() {
		Node node = null;
		
		NodeType[] nodeTypes = new NodeType[] { NodeType.OKW };
		Node mainNode = new Node();
		mainNode.setNodeType(NodeType.OKW);

		WzdAddEditNode wzdAddEditNode = new WzdAddEditNode(true, mainNode, nodeTypes);
		WizardDialog wzdDlg = new WizardDialog(shlMain, wzdAddEditNode);
		wzdDlg.open();
		if (wzdDlg.getReturnCode() == IDialogConstants.OK_ID) {
			node = mainNode;
		}
		
		return node;
	}

	protected void createContents() {
		createShlMain();

	}

	private void createShlMain() {
		shlMain = new Shell();
		shlMain.setMinimumSize(new Point(640, 480));
		shlMain.setSize(1024, 800);
		shlMain.setLocation(5, 5);
		Node mainNode = manager.getMainNode();
		if(mainNode == null) {
			shlMain.setText("Daj Głos - OKW");
		} else {
			shlMain.setText("Daj Głos - OKW: " + mainNode.getName() + "[" + mainNode.getLocatorURI() + "]");
		}
		shlMain.setLayout(new GridLayout(2, false));

		tblVwrMain = new TableViewer(shlMain, SWT.BORDER | SWT.FULL_SELECTION);
		tblMain = tblVwrMain.getTable();
		tblMain.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

		TableViewerColumn tblVwrClmnDate = new TableViewerColumn(tblVwrMain, SWT.NONE);
		tblVwrClmnDate.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : Converter.dateToString(((Message) element).getDate());
			}
		});
		TableColumn tblclmnDate = tblVwrClmnDate.getColumn();
		tblclmnDate.setWidth(200);
		tblclmnDate.setText("New Column");

		TableViewerColumn tblVwrClmnMessage = new TableViewerColumn(tblVwrMain, SWT.NONE);
		tblVwrClmnMessage.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Message) element).getText();
			}
		});
		TableColumn tblclmnMessage = tblVwrClmnMessage.getColumn();
		tblclmnMessage.setWidth(800);
		tblclmnMessage.setText("Message");

		Composite cmpButtons = new Composite(shlMain, SWT.NONE);
		cmpButtons.setLayout(new GridLayout(1, false));
		cmpButtons.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));

		btnCheckConnection = new Button(cmpButtons, SWT.NONE);
		btnCheckConnection.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				dlgCommunicationState = new DlgCommunicationState(shlMain, manager);
				dlgCommunicationState.open();
				dlgCommunicationState = null;
			}
		});
		btnCheckConnection.setBounds(0, 0, 90, 30);
		btnCheckConnection.setText("Check connection");

		Label label = new Label(cmpButtons, SWT.SEPARATOR | SWT.HORIZONTAL);
		label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));

		btnClearMessages = new Button(cmpButtons, SWT.NONE);
		btnClearMessages.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				messageList.clear();
				tblVwrMain.refresh();
			}
		});
		btnClearMessages.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		btnClearMessages.setText("Clear messages");
		tblVwrMain.setContentProvider(new ContentProvider());
		tblVwrMain.setInput(messageList);
		
		appendMessage("Uruchomiono");
	}

	public void appendMessage(final String messageText) {
		Display.getDefault().asyncExec(new Runnable() {
			@Override
			public void run() {
				messageList.add(0, new Message(messageText));
				tblVwrMain.refresh();
			}
		});
	}

	class Message {
		private Date date;
		private String messageText;

		public Message(String messageText) {
			this.date = new Date();
			this.messageText = messageText;
		}

		public Message(Date date, String messageText) {
			this.date = date;
			this.messageText = messageText;
		}

		public Date getDate() {
			return date;
		}

		public String getText() {
			return messageText;
		}
	}
}
